package com.mindata.blockchain.core.manager;

import com.mindata.blockchain.socket.raft.core.proto.RaftMessage;
import com.google.common.collect.Lists;
import com.mindata.blockchain.common.ResultPack;
import com.mindata.blockchain.core.bean.RaftConfigData;
import com.mindata.blockchain.core.bean.RaftServer;
import com.mindata.blockchain.socket.raft.admin.RaftClientServiceProxy;
import com.mindata.blockchain.socket.raft.core.service.RaftClientService;
import com.mindata.blockchain.socket.raft.utils.RaftUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * User: jasperxgwang
 * Date: 2018-8-15 19:49
 */
@Service
@Slf4j
public class RaftManager {

    @Resource
    private PermissionManager permissionManager;

    /**
     * 获取raft服务配置
     *
     * @return
     */
    public ResultPack<RaftConfigData> getConfiguration() {
        String servers = permissionManager.getRaftClusterEndPoints();
        RaftClientService client = new RaftClientServiceProxy(servers);

        RaftMessage.GetConfigurationRequest request = RaftMessage.GetConfigurationRequest.newBuilder().build();
        RaftMessage.GetConfigurationResponse response = client.getConfiguration(request);
        try {
            if (response != null) {
                if (response.getResCode() == RaftMessage.ResCode.RES_CODE_SUCCESS) {
                    RaftConfigData data = new RaftConfigData();
                    RaftMessage.Server server = response.getLeader();
                    data.setLeader(new RaftServer(server.getEndPoint().getHost(),
                            server.getEndPoint().getPort(), server.getServerId()));
                    List<RaftServer> srvs = Lists.newArrayList();
                    response.getServersList().forEach(e -> {
                        srvs.add(new RaftServer(e.getEndPoint().getHost(),
                                e.getEndPoint().getPort(), e.getServerId()));
                    });
                    data.setServers(srvs);
                    return ResultPack.succeed(data);
                } else {
                    return ResultPack.failed(response.getResMsg());
                }
            }
            return ResultPack.failed("no response");
        } catch (Exception ex) {
            log.error("getConfiguration error", ex);
            return ResultPack.failed("system error:{}", ex.getMessage());
        } finally {
            ((RaftClientServiceProxy) client).stop();
        }
    }

    /**
     * 新增节点
     *
     * @param serversString 127.0.0.1:5001:1,127.0.0.1:5002:2
     * @return
     */
    public ResultPack<String> addPeers(String serversString) {
        String servers = permissionManager.getRaftClusterEndPoints();
        RaftClientService client = new RaftClientServiceProxy(servers);

        List<RaftMessage.Server> serverList = RaftUtils.parseServers(serversString);
        RaftMessage.AddPeersRequest request = RaftMessage.AddPeersRequest.newBuilder().addAllServers(serverList).build();
        RaftMessage.AddPeersResponse response = client.addPeers(request);
        try {
            if (response != null) {
                if (response.getResCode() == RaftMessage.ResCode.RES_CODE_SUCCESS) {
                    return ResultPack.succeed();
                } else {
                    return ResultPack.failed(response.getResMsg());
                }
            }
            return ResultPack.failed("no response");
        } catch (Exception ex) {
            log.error("addPeers error", ex);
            return ResultPack.failed("system error:{}", ex.getMessage());
        } finally {
            ((RaftClientServiceProxy) client).stop();
        }
    }

    /**
     * 删除节点
     *
     * @param serversString 127.0.0.1:5001:1,127.0.0.1:5002:2
     * @return
     */
    public ResultPack<String> delPeers(String serversString) {
        String servers = permissionManager.getRaftClusterEndPoints();
        RaftClientService client = new RaftClientServiceProxy(servers);

        List<RaftMessage.Server> serverList = RaftUtils.parseServers(serversString);
        RaftMessage.RemovePeersRequest request = RaftMessage.RemovePeersRequest.newBuilder().addAllServers(serverList).build();
        RaftMessage.RemovePeersResponse response = client.removePeers(request);
        try {
            if (response != null) {
                if (response.getResCode() == RaftMessage.ResCode.RES_CODE_SUCCESS) {
                    return ResultPack.succeed();
                } else {
                    return ResultPack.failed(response.getResMsg());
                }
            }
            return ResultPack.failed("no response");
        } catch (Exception ex) {
            log.error("delPeers error", ex);
            return ResultPack.failed("system error:{}", ex.getMessage());
        } finally {
            ((RaftClientServiceProxy) client).stop();
        }
    }

}
